//
//  DouglasPeuckerUtil.swift
//  AreaMeasureDevice
//
//  Created by iOS on 2021/5/25.
//

import Foundation
import MapKit

class DouglasPeuckerUtil {

    /// 初始接收数据列表
    private var tracePoints:[MALonLatPoint] = []
    /// 处理过的数据列表
    var smoothPoints:[MALonLatPoint]!
    /// 需返回的经纬度点数据表
    private var polyCoordList:[CLLocationCoordinate2D] = []

    private lazy var tool:MASmoothPathTool = {
        let tool = MASmoothPathTool()
        tool.intensity = 3
        tool.threshHold = 0.1
        tool.noiseThreshhold = 5
        return tool
    }()

    func compress(coord:CLLocationCoordinate2D){
        let point = MALonLatPoint()
        point.lat = coord.latitude
        point.lon = coord.longitude
        point.altitude = 0
        self.tracePoints.append(point)
        if self.tracePoints.count < 3{return}
        self.smoothPoints = tool.pathOptimize(self.tracePoints)
    }

    func compress(model:RealtimeDataModel){
        let point = MALonLatPoint()
        point.lat = model.latitude
        point.lon = model.longitude
        point.altitude = Double(model.altitude)
        self.tracePoints.append(point)
        if self.tracePoints.count < 3{return}
        self.smoothPoints = tool.pathOptimize(self.tracePoints)
    }

    func getSmoothPathPoints()->[CLLocationCoordinate2D]{
        if self.smoothPoints != nil {
            self.polyCoordList.removeAll()
            self.smoothPoints!.forEach { (point) in
//                debugPrint("latLong == ", point.latLon)
                let coor = CLLocationCoordinate2D(latitude: point.lat, longitude: point.lon)
                self.polyCoordList.append(coor)
            }
        }
        return self.polyCoordList
    }



    /// 道格拉斯抽稀算法
    /// 没有去噪及平滑处理
    /// - Parameters:
    ///   - locaCoords: 需处理的经纬点列表
    ///   - epsilon: 阙值
    /// - Returns: 处理过的经纬点列表
    func compress(locaCoords:[CLLocationCoordinate2D], epsilon:Double) -> [CLLocationCoordinate2D] {
        let pointList = locaCoords
        // 递归进行调用筛选
        var maxDist:Double = 0
        var currentIndex:Int = 0 //分割位
        let end = pointList.count
        for i in 1 ..< end-1 {
            let currentDist = distToSegment(startPoint: pointList[0], endPoint: pointList[end-1], centerPoint: pointList[i])
            if currentDist > maxDist {
                maxDist = currentDist
                currentIndex = i
//                debugPrint("maxDist == ", maxDist)
//                debugPrint("currentIndex == ", currentIndex)
            }
        }
        var result = Array<CLLocationCoordinate2D>()
        if maxDist >= epsilon {
            var leftPoints:[CLLocationCoordinate2D] = [] // 左曲线
            var rightPoints:[CLLocationCoordinate2D] = [] //右曲线
            //分别提取出左曲线和右曲线的坐标点
            for i in 0 ..< end {
                if i <= currentIndex {
                    leftPoints.append(pointList[i])
                    if i == currentIndex {
                        rightPoints.append(pointList[i])
                    }
                }else{
                    rightPoints.append(pointList[i])
                }
            }
            var leftResult = compress(locaCoords: leftPoints, epsilon: epsilon)
            var rightResult = compress(locaCoords: rightPoints, epsilon: epsilon)
            if rightResult.count > 0 {
                rightResult.remove(at: 0)
            }
            leftResult.append(contentsOf: rightResult)
            result = leftResult
        }else{
            result.append(pointList[0])
            result.append(pointList[end-1])
        }
        return result
    }


    /// 使用三角形面积（使用海伦公式求得）相等方法计算点pX到点pA和pB所确定的直线的距离
    /// - Parameters:
    ///   - start: 起始点
    ///   - end: 结束点
    ///   - center: 前两个点之间的中心点
    /// - Returns: 中心点到 start和end所在直线的距离
    private func distToSegment(startPoint:CLLocationCoordinate2D, endPoint:CLLocationCoordinate2D, centerPoint:CLLocationCoordinate2D) -> Double {
        let startPoint = CLLocation(latitude: startPoint.latitude, longitude: startPoint.longitude)
        let endPoint = CLLocation(latitude: endPoint.latitude, longitude: endPoint.longitude)
        let centerPoint = CLLocation(latitude: centerPoint.latitude, longitude: centerPoint.longitude)
        let a = fabs(startPoint.distance(from: endPoint))
        let b = fabs(startPoint.distance(from: centerPoint))
        let c = fabs(endPoint.distance(from: centerPoint))
        let p = (a + b + c) / 2.0
        let s = sqrt(fabs(p * (p - a) * (p - b) * (p - c)))
        let d = s * 2.0 / a
        return d
    }


}

